#include<stdio.h>
#include<stdlib.h> // malloc, exit
#include<unistd.h> // fork
#include<signal.h>
#include<sys/stat.h>
#include<fcntl.h>



int ngx_daemon()
{
    int fd;

    switch (fork())
    {
    case -1:
        printf("创建子进程失败 \n");
        return -1;
    case 0:
        printf("子进程，直接break \n");
        break;
    default:
        printf("父进程，程序直接exit(0) \n");
        exit(0);
    }
    // 只有子进程才会往下走

    // 脱离终端，终端关闭，将与此子进程无关
    if (-1 == setsid())
    {
        printf("sersid error \n");
        return -1;
    }

    // 设置为0，不要让它限制文件权限，以免引起混乱
    umask(0); 

    // 以读写方式打开黑洞设备
    fd = fopen("/dev/null", O_RDWR);
    if (-1 == fd)
    {
        printf("fopen error \n");
        return -1;
    }

    // 先关闭 STSIN_FILENO 标准输入
    if (-1 == dup2(fd, STDIN_FILENO))
    {
        printf("dup2 STDIN_FILENO error \n");
        return -1;
    }

    // 先关闭 STSOUT_FILENO 标准输出
    if (-1 == dup2(fd, STDOUT_FILENO))
    {
        printf("dup2 STSOUT_FILENO error \n");
        return -1;
    }

    if (fd > STDERR_FILENO) // 标准错误
    {
        if (-1 == close(fd))
        {
            printf("close fd error \n");
            return -1;
        }
    }

    return 1;
    
}

int main(int argc, char *const *argv)
{
    printf("程序开始执行 \n");

    if ( 1 != ngx_daemon())
    {
        printf("ngx_darmon error \n");
        return 1;
    }
    else
    {
        // 创建守护进程成功
        for (; ; )
        {
            sleep(1);
            printf("进程休息1s, 进程ID = %d \n", getpid());
        } 
    }
    

    printf("程序执行结束 \n");

    return 0;
}
